﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls.WebParts;

namespace Trentacular.SharePoint.Features.Web.UI.WebParts
{
    public class WebEditableWebPart : BaseWebPart, IWebEditable
    {
        private class EditorPartRegistration
        {
            public string ID { get; private set; }
            public string Title { get; private set; }
            public string UserControlVirtualPath { get; private set; }
            public Type EditorPartType { get; private set; }

            private EditorPartRegistration(string id, string title)
            {
                ID = id;
                Title = title;
            }

            public EditorPartRegistration(string id, string title, string userControlVirtualPath) :
                this(id, title)
            {
                UserControlVirtualPath = userControlVirtualPath;
            }

            public EditorPartRegistration(string id, string title, Type editorPartType) :
                this(id, title)
            {
                EditorPartType = editorPartType;
            }
        }

        private IList<EditorPartRegistration> _registeredEditors;
        private IList<EditorPartRegistration> RegisteredEditors
        {
            get
            {
                if (_registeredEditors == null)
                    _registeredEditors = new List<EditorPartRegistration>();
                return _registeredEditors;
            }
        }

        protected void RegisterEditorPart(string id, string title, string userControlVirtualPath)
        {
            RegisteredEditors.Add(new EditorPartRegistration(id, title, userControlVirtualPath));
        }

        protected void RegisterEditorPart<T>(string id, string title) where T : EditorPart
        {
            RegisteredEditors.Add(new EditorPartRegistration(id, title, typeof(T)));
        }

        private EditorPart InstantiateEditor(EditorPartRegistration registration)
        {
            var editorPartType = registration.EditorPartType;
            EditorPart editor = null;
            if (editorPartType != null)
                editor = (EditorPart)Activator.CreateInstance(editorPartType);
            else
                editor = (EditorPart)Activator.CreateInstance(
                    typeof(ControlWrapperEditorPart<>).MakeGenericType(this.GetType()),
                    registration.UserControlVirtualPath
                    );

            editor.ID = string.Format("{0}_{1}", this.ID, registration.ID);
            editor.Title = registration.Title;
            return editor;
        }

        #region IWebEditable Members

        EditorPartCollection IWebEditable.CreateEditorParts()
        {
            var editors = RegisteredEditors.Select(reg => InstantiateEditor(reg)).ToList();
            return new EditorPartCollection(editors);
        }

        object IWebEditable.WebBrowsableObject
        {
            get { return this; }
        }

        #endregion
    }
}
